package com.example.demo.service.comm;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.utils.regex.RegexUtil;
import com.mongodb.BasicDBObject;
import org.bson.Document;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.util.StringUtils;

import java.io.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

/**
 * @description:
 * @author: cj
 * @create: 16-03-17 16:50:08
 */
public class JsonUtil {
    /**
     * @param patch   josn 文件的路基
     * @param jsonKey 对应的key
     * @param parMap  条件
     * @return aggregation
     */
    public static List<AggregationOperation> aggregation(String patch, String jsonKey, Map<String, Object> parMap) {
        String replaceV2 = init ( patch, jsonKey, parMap );
        List<Map> mapList = JSON.parseArray ( replaceV2, Map.class );
        List<AggregationOperation> operationList = new ArrayList<> ();
        for (Map map : mapList) {
            AggregationOperation operation = var -> new Document ( map );
            operationList.add ( operation );
        }
        return operationList;
    }

    private static String init(String patch, String jsonKey, Map<String, Object> parMap) {
        patch = Class.class.getClass ().getResource ( "/json" ).getPath () + "/" + patch;
        String jsonStr = readJsonStr ( patch );
        Map jsonMap = JSONObject.parseObject ( jsonStr, Map.class );
        String text = jsonMap.get ( jsonKey ).toString ();
        return replaceV2 ( text, parMap );
    }

    public static BasicDBObject basicDBObject(String patch, String jsonKey, Map<String, Object> parMap) {

        String replaceV2 = init ( patch, jsonKey, parMap );
        return JSON.parseObject ( replaceV2, BasicDBObject.class );
    }

    /**
     * 1、先获取到文件的所在位置
     * 2、获取对应的key
     * 3、根据key对应的value值和对应的map条件转换成对应的map
     * 4、放到对应的语句中
     */
    /**
     * @param path
     * @return
     */
    public static String readJsonStr(String path) {
        StringBuffer res = new StringBuffer ();
        String line = null;
        try {
            InputStreamReader isr = new InputStreamReader ( new FileInputStream ( path ), "gbk" );
            //BufferedReader reader = new BufferedReader(new FileReader(file));
            BufferedReader br = new BufferedReader ( isr );
            while ((line = br.readLine ()) != null) {
                res.append ( line );
            }
            br.close ();
        } catch (FileNotFoundException e) {
            e.printStackTrace ();
        } catch (IOException e) {
            e.printStackTrace ();
        }
        return res.toString ();
    }

    /**
     * @param text 文本
     * @param map  替换 的map
     * @return
     */
    private static String replaceV2(String text, Map<String, Object> map) {
        List<String> keys = new ArrayList<> ();
        // 把文本中的所有需要替换的变量捞出来, 丢进keys
        Matcher matcher = RegexUtil.getRepalse ( text );
        while (matcher.find ()) {
            String key = matcher.group ();
            if (!keys.contains ( key )) {
                keys.add ( key );
            }
        }
        // 开始替换, 将变量替换成数字,  并从map中将对应的值丢入 params 数组
        Object[] params = new Object[keys.size ()];
        for (int i = 0; i < keys.size (); i++) {
            text = text.replaceAll ( "#" + keys.get ( i ), i + "" );
            params[i] = map.get ( keys.get ( i ) );
        }

        String parse = parse ( text, params );
        return parse;
    }

    public static String replace(String text, Object... args) {
        return MessageFormat.format ( text, args );
    }

    public static String parse(String text, Object... args) {
        return parse ( "\"#{", "}\"", text, args );
    }

    /**
     * 将字符串text中由openToken和closeToken组成的占位符依次替换为args数组中的值
     *
     * @param openToken  占位符
     * @param closeToken 占位符
     * @param text       字符串
     * @param args       替换
     * @return 字符串
     */
    public static String parse(String openToken, String closeToken, String text, Object... args) {
        if (args == null || args.length <= 0) {
            return text;
        }
        int argsIndex = 0;
        if (text == null || text.isEmpty ()) {
            return "";
        }
        char[] src = text.toCharArray ();
        int offset = 0;
        // search open token
        int start = text.indexOf ( openToken, offset );
        if (start == -1) {
            return text;
        }
        final StringBuilder builder = new StringBuilder ();
        StringBuilder expression = null;
        while (start > -1) {
            if (start > 0 && src[start - 1] == '\\') {
                // this open token is escaped. remove the backslash and continue.
                builder.append ( src, offset, start - offset - 1 ).append ( openToken );
                offset = start + openToken.length ();
            } else {
                // found open token. let's search close token.
                if (expression == null) {
                    expression = new StringBuilder ();
                } else {
                    expression.setLength ( 0 );
                }
                builder.append ( src, offset, start - offset );
                offset = start + openToken.length ();
                int end = text.indexOf ( closeToken, offset );
                while (end > -1) {
                    if (end > offset && src[end - 1] == '\\') {
                        // this close token is escaped. remove the backslash and continue.
                        expression.append ( src, offset, end - offset - 1 ).append ( closeToken );
                        offset = end + closeToken.length ();
                        end = text.indexOf ( closeToken, offset );
                    } else {
                        expression.append ( src, offset, end - offset );
//                        offset = end + closeToken.length();
                        break;
                    }
                }
                if (end == -1) {
                    // close token was not found.
                    builder.append ( src, start, src.length - start );
                    offset = src.length;
                } else {
                    ///////////////////////////////////////仅仅修改了该else分支下的个别行代码////////////////////////
                    String value = (argsIndex <= args.length - 1) ?
                            (args[argsIndex] == null ? "" : args[argsIndex].toString ()) : expression.toString ();
//                    if (args[argsIndex] instanceof Integer || args[argsIndex] instanceof Boolean){
//                        builder.append( Integer.valueOf( value ) );
//                    }else {
//                        builder.append( "\""+value+"\"" );
//                    }
                    builder.append ( args[argsIndex] instanceof Integer ? Integer.valueOf ( value ) : args[argsIndex] instanceof Boolean
                            ? Boolean.valueOf ( value ) : "\"" + value + "\"" );
                    offset = end + closeToken.length ();
                    argsIndex++;
                    ////////////////////////////////////////////////////////////////////////////////////////////////
                }
            }
            start = text.indexOf ( openToken, offset );
        }
        if (offset < src.length) {
            builder.append ( src, offset, src.length - offset );
        }
        return builder.toString ();
    }

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<> ();
        map.put ( "a", 1 );

        map.put ( "b", null );
        boolean b = StringUtils.isEmpty ( map.get ( "a" ) );
        System.out.println ( "b = " + b );
    }
}
